#pragma once

#include <iostream>
#include <queue>
#include <pthread.h>
#include "Task.hpp"
#include "Log.hpp"

#define NUM 7

//单例线程池
class ThreadPool
{
private:
    int _num;                       //总线程数
    bool _stop;                     //是否停止
    std::queue<Task> _taskQueue;    //任务队列
    pthread_mutex_t _lock;          //任务队列锁
    pthread_cond_t _cond;           //条件变量

    static ThreadPool* thePoolInstance;
private:
    ThreadPool(int num = NUM)
        :_num(num)
        ,_stop(false)
    {
        pthread_mutex_init(&_lock, nullptr); 
        pthread_cond_init(&_cond, nullptr);
    }

    ThreadPool(const ThreadPool& other) = delete;
public:
    static ThreadPool* GetInstance()
    {
        static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

        if(thePoolInstance==nullptr)
        {
            pthread_mutex_lock(&mtx);
            if(thePoolInstance==nullptr)
            {
                thePoolInstance = new ThreadPool;
                thePoolInstance->Init();
            }
            pthread_mutex_unlock(&mtx);
        }
        return thePoolInstance;
    }

    bool IsStop()
    {
        return _stop;
    }
    

    bool IsTaskQueueEmpty()
    {
        return !_taskQueue.size();
    }
    
    //pthread_mutex_lock(&锁)
    void Lock()
    {
        pthread_mutex_lock(&_lock);
    }
    
    //pthread_mutex_unlock(&锁)
    void UnLock()
    {
        pthread_mutex_unlock(&_lock);
    }
    
    //初始线程池以及任务队列
    bool Init()
    {
        for(int i = 0; i< _num; i++)
        {
            pthread_t tid;
           if(0 != pthread_create(&tid, nullptr,  Routine, this))
           {
                LOG(FATAL, "pthread_create fail");
                return false; 
           }
        }
        LOG(NORMAL, "Thread init success");
        return true;
    }
    
    //线程执行的Routine
    static void* Routine(void* args)
    {
        ThreadPool* pPool = (ThreadPool*)args;
        while(1)
        {
            Task task;
            pPool->Lock();      //加锁
            while(pPool->IsTaskQueueEmpty())    //条件变量等待的条件
            {
                pPool->Wait();                  //任务队列为空就休眠
            }

            pPool->PopTask(task);

            pPool->UnLock();    //解锁
            task.ProcessOn();   //处理任务
        }
    }

    //pthread_cond_wait(&条件变量, &锁);
    void Wait()
    {
        pthread_cond_wait(&_cond, &_lock);
    }
    
    //pthread_cond_signal(&条件变量);
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    
    //进任务队列
    void PushTask(const Task& task)
    {
        Lock();
        _taskQueue.push(task);
        UnLock();
        //有任务了，就要唤醒休眠等待任务的线程
        WakeUp();
    }

    //出任务队列(线程拿取任务)
    void PopTask(Task& task)
    {
        task = _taskQueue.front();
        _taskQueue.pop();
    }


    ~ThreadPool()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }
};

ThreadPool* ThreadPool::thePoolInstance = nullptr;

